/**
	License:		Artistic license 2.0 (see license.txt, also available online at http://www.perlfoundation.org/artistic_license_2_0)
	Authors:		OrbitalLab (http://www.orbitallab.ru/moonglide/), 2007-2009

	File:			ResShader.d
	Description:	shader resource
	Date:			23.11.2007 by Digited
*/
module moonglide.resources.resobjects.lowlevel.ResShader;

import moonglide.resources.Management;

enum : ubyte
{
	sh_Vertex = 0,
	sh_Fragment = 1,
	sh_Geometry = 2
}

struct SShaderLoc
{
	protected:
		Vector4f	fdata;
		Point4i		idata;

	public:
		bool		isStatic = true,
					binded = false,
					floatUse = true;

	ubyte 			size;

	char[]			name;	// GLSL : id			ARB : only for programmer
	uint			num;	// GLSL : not used		ARB : id

	Vector4f getFData() { return fdata; }
	Point4i getIData() { return idata; }

	void setData( in float fData )
	{
		floatUse = true;
		fdata.x = fData;
		size = 1;
	}
	void setData( in Vector2f f2Data )
	{
		floatUse = true;
		fdata.x = f2Data.x;	fdata.y = f2Data.y;
		size = 2;
	}
	void setData( in Vector3f f3Data )
	{
		floatUse = true;
		fdata.x = f3Data.x;	fdata.y = f3Data.y; 	fdata.z = f3Data.z;
		size = 3;
	}
	void setData( in Vector4f f4Data )
	{
		floatUse = true;
		fdata = f4Data;
		size = 4;
	}

	void setData( in int iData )
	{
		floatUse = false;
		idata.x = iData;
		size = 1;
	}
	void setData( in Point2i i2Data )
	{
		floatUse = false;
		idata.x = i2Data.x;	idata.y = i2Data.y;
		size = 2;
	}
	void setData( in Point3i i3Data )
	{
		floatUse = false;
		idata.x = i3Data.x;	idata.y = i3Data.y; 	idata.z = i3Data.z;
		size = 3;
	}
	void setData( in Point4i i4Data )
	{
		floatUse = false;
		idata = i4Data;
		size = 4;
	}
}

//============================================================
/// Shader program special class
//============================================================
class CResShader : IResource
{
	protected:
		this( char[] idname )
		{
			handle = 0;
			super( idname );
		}

	public:
		SShaderLoc[] locals;

		uint		handle;		//for glGenProgramsARB in ARB
		uint		sType; 		//sh_Vertex,	sh_Fragment,	sh_Geometry
		char[][]	text;		//source code
		char[][]	define;

		void setDefine(char[] defname)
		{
			text = "#define " ~ defname ~'\n'~text;
			define ~= defname;
		}

		//============================================================
		/// opCall - main resource getter
		//============================================================
		static CResShader opCall( char[] id, bool load = false, char[] errorResource = "" )
		{
			// check for registered ONLY in case we want to load resource
			if( load )
			{
				if( CResManager().Exists( id ))
					debug
					{
						auto tmp = cast(CResShader)CResManager().GetResource( id );
						moonAssert( tmp !is null, "casting GetResource to CResShader failed", __FILE__, __LINE__ );
						return tmp;
					}
					else
					{
						return cast(CResShader)CResManager().GetResource( id );
					}

				auto res = new CResShader( id );

				_Load( res, errorResource );
				debug moonAssert( res !is null, "loading CResShader returned null", __FILE__, __LINE__ );
				return res;
			}

			// if we do not load, just gen unique name and create new with it.
			CResManager().GenerateUniqueName( id );
			auto res = new CResShader( id );

			_New( res );
			return res;
		}


		// destructor
		~this() {}
}
